﻿using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using ColliderSystem;
using NFixedPoint;
using UnityEngine;

namespace ColliderSystem
{
    public class ColliderSyster
    {
        public List<IShape> shapeList = new List<IShape>();

        public ColliderSyster(string path)
        {
            var list = DeserializeObject<List<ShapeInfo>>(path);
            Debug.LogError("[加载配置info成功]" + list);

            foreach (var item in list)
            {
                if (item is BoxInfo box)
                {
                    shapeList.Add(new NBoxCollider(box));
                }
                else if (item is SphereInfo sphere)
                {
                    shapeList.Add(new NSphereCollider(sphere));
                }
            }
        }

        T DeserializeObject<T>(string path)
        {
            if (File.Exists(path))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                using (FileStream stream = new FileStream(path, FileMode.Open))
                {
                    return (T)formatter.Deserialize(stream);
                }
            }
            else
            {
                return default(T);
            }
        }

        public void CollisionDetection(NSphereCollider player, FixedPoint3 v)
        {
            //位置预判，后面如果碰到会拉回来
            player.info.position += v;
            //拿到当前场景所有碰到的场景
            List<IShape> infoList = GetCollisionInfoList(player);
            if (infoList.Count == 1)
            {
                //只碰到一个；
                PositionAdjust(player, infoList[0], v);
            }
            else if (infoList.Count > 1)
            {
                //大于一个，直接位置拉回
                player.info.position -= v;
            }
        }

        void PositionAdjust(NSphereCollider sphere, IShape fromInfo, FixedPoint3 v)
        {
            FixedPoint3 normal = FixedPoint3.zero;
            FixedPoint3 adjust = FixedPoint3.zero;
            if (fromInfo is NBoxCollider col)
            {
                FixedPoint3 point = sphere.GetClosePoint(col);

                //碰撞体中心与点的距离
                FixedPoint3 dis = sphere.info.position - point;
                normal = dis.normalized;
                adjust = normal * (sphere.info.radius - dis.magnitude);
            }
            else if (fromInfo is NSphereCollider col2)
            {
                //2 个圆形的距离
                FixedPoint3 offset = sphere.info.position - col2.info.position;
                //碰到了，计算坐标和法线
                normal = offset.normalized;
                adjust = normal * (sphere.info.radius + col2.info.radius - offset.magnitude);
            }
            sphere.info.position += adjust;
        }

        List<IShape> GetCollisionInfoList(NSphereCollider player)
        {
            List<IShape> infoList = new List<IShape>();
            foreach (var colliderShape in shapeList)
            {
                var i = player.Intersects(colliderShape);
                if (i != null)
                {
                    infoList.Add(i);
                }
            }
            return infoList;
        }
    }
}
